﻿// Copyright (c) 2012 - 2021 Jared Zheng <jaredz at outlook dot com>
// Buddha Framework is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
// EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
// MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.
//
// Create : 2012-12-01 version 0.1 Jared Zheng <jaredz at outlook dot com>
// Update : 2021-03-19 version 4.0.0 Jared Zheng <jaredz at outlook dot com>

#ifndef __SLAVE_SERVER_H__
#define __SLAVE_SERVER_H__

#pragma once

#include "CommonPacket.h"
#include "CommonServer.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////
// slave
class CSlaveServer : public ICommonFrame, public CPAKHandler
{
public:
    CSignalEvent Events; // 业务层事件信号
public:
    CSlaveServer(void);
    virtual ~CSlaveServer(void);
    // CComponent
    virtual UInt   Command(PCXStr pszCMD, uintptr_t utParam) OVERRIDE;
    virtual UInt   Update(void) OVERRIDE;
    // ICommonFrame
    virtual UInt   Init(CEventHandler& EventHandlerRef, CServerConfig& ConfigRef, UInt uRank) OVERRIDE;
    virtual void   Exit(void) OVERRIDE;

    virtual bool   Start(void) OVERRIDE;
    virtual void   Stop(bool bUnlink) OVERRIDE;

    virtual CServerConfig&    GetConfig(void) OVERRIDE;
    virtual CEventHandlerPtr& GetMgrHandler(void) OVERRIDE;
    virtual CNetworkPtr&      GetNetworkPtr(void) OVERRIDE;
    virtual CFileLogPipe&     GetFileLog(void) OVERRIDE;
    virtual CSignalEvent&     GetSignalEvent(void) OVERRIDE;
    virtual SERVER_DATA&      GetData(void) OVERRIDE;
    virtual SERVER_CLUSTER&   GetCluster(UInt uRank, bool bLocal = true) OVERRIDE;
    // CPAKHandler
    virtual bool   OnTcpDispatch(const PacketPtr& PktPtr, PTCP_PARAM pTcp) OVERRIDE;
    virtual bool   OnTcpAccept(Socket sAccept, Socket sListen) OVERRIDE;
    virtual bool   OnTcpConnect(UInt uError, Socket_t sConnect) OVERRIDE;
    virtual bool   OnTcpClose(Socket sSocket, ULLong ullLiveData) OVERRIDE;
private:
    CSlaveServer(const CSlaveServer&);
    CSlaveServer& operator=(const CSlaveServer&);
    // 从配置加载数据
    bool  LoadConfig(void);
    // 清除从配置加载的数据
    void  UnloadConfig(void);
    // 按配置信息加载业务层
    bool  LoadRoutine(void);
    // 释放加载的业务层
    void  UnloadRoutine(void);
    //--------------------------------------
    bool  StartListen(void);
    void  CheckListen(void);
    void  StopListen(void);

    void  CheckUpdate(void);
    // 按层级从小向大同步服务信息
    void  SyncUpdate(void);
    void  SyncServer(UInt uRank);

    bool  OnCommonEvent(UInt uRank, const PacketPtr& PktPtr, Socket_t sSocket);

    bool  OnLink(UInt uRank, Socket_t sSocket, CNETHead* pLink);
    bool  OnUpdate(UInt uRank, Socket_t sSocket, CNETHead* pUpdate);
    bool  OnSync(UInt uRank, Socket_t sSocket, CPAKHead* pSync);
    bool  OnUnlink(UInt uRank, Socket_t sSocket, CPAKHead* pHead);

    // 注册服务
    bool  LinkServer(UInt uRank, Socket_t sSocket, CNETHead* pLink);
    // 更新服务
    bool  UpdateServer(UInt uRank, Socket_t sSocket, CNETHead* pUpdate);
    // 同步服务
    bool  SyncServer(UInt uRank, Socket_t sSocket, CPAKHead* pSync);
    // 注销服务
    bool  UnlinkServer(UInt uRank, Socket_t sSocket, UInt uType);

    bool  AddSync(UInt uRank, UInt uSync, Socket_t sSocket);
    bool  RemoveSync(UInt uRank, UInt uSync, Socket_t sSocket);

    bool  SyncServerPack(SERVER_CLUSTER& Cluster, PINDEX& index, ARY_SYNC& aSocket, UInt uRank);
    bool  SyncServerPack(SERVER_CLUSTER& Cluster, PINDEX& index, Socket_t sSocket, UInt uRank);
    //--------------------------------------
    bool  StartConnect(void);
    void  StopConnect(void);

    bool  StartConnect(UInt uRank);
    bool  CheckConnect(UInt uRank);
    void  StopConnect(UInt uRank);

    void  CheckUpdate(UInt uRank, bool bLive);

    void  LinkServer(UInt uRank);
    void  UnlinkServer(UInt uRank);

    void  OnLinkAck(UInt uRank, CPAKHead* pLinkAck, Socket_t sSocket);
    void  OnSyncAck(UInt uRank, CNETSync* pSyncAck, Socket_t sSocket);
    void  OnUnlinkAck(UInt uRank, Socket_t sSocket);
    //--------------------------------------
    SERVER_CLUSTER& SyncCluster(UInt uRank);
    void  CleanCluster(void);
private:
    Int                m_nLiveStep;
    Int                m_nLiveUpdate;
    CServerConfig*     m_pConfig;
    CFileLogPipe       m_FileLog;
    CEventHandlerPtr   m_MgrHandler;
    CNetworkPtr        m_NetworkPtr;
    CRoutinePtr        m_RoutinePtr;
    SERVER_DATA        m_SrvData;
    // 从Master同步的服务信息
    // 如果m_SrvData.uSync有对应的同步服务的标志位
    // 就取从Master同步的服务信息同步给其他服务
    SERVER_CLUSTER     m_Master[COMMONR_MAX];

    SERVER_CLUSTER     m_Cluster[COMMONR_MAX];
    SERVER_SYNC        m_Sync[COMMONR_MAX];
};

INLINE CSlaveServer::CSlaveServer(void)
: m_nLiveStep(-1)
, m_nLiveUpdate(0)
, m_pConfig(nullptr)
, m_FileLog(false)
{
}

INLINE CSlaveServer::~CSlaveServer(void)
{
}

INLINE CSlaveServer::CSlaveServer(const CSlaveServer&)
: m_nLiveStep(-1)
, m_nLiveUpdate(0)
, m_pConfig(nullptr)
, m_FileLog(false)
{
}

INLINE CSlaveServer& CSlaveServer::operator=(const CSlaveServer&)
{
    return (*this);
}

INLINE CServerConfig& CSlaveServer::GetConfig(void)
{
    return (*m_pConfig);
}

INLINE CEventHandlerPtr& CSlaveServer::GetMgrHandler(void)
{
    return m_MgrHandler;
}

INLINE CNetworkPtr& CSlaveServer::GetNetworkPtr(void)
{
    return m_NetworkPtr;
}

INLINE CFileLogPipe& CSlaveServer::GetFileLog(void)
{
    return m_FileLog;
}

INLINE CSignalEvent& CSlaveServer::GetSignalEvent(void)
{
    return Events;
}

INLINE SERVER_DATA& CSlaveServer::GetData(void)
{
    return m_SrvData;
}

INLINE SERVER_CLUSTER& CSlaveServer::GetCluster(UInt uRank, bool bLocal)
{
    if (uRank < COMMONR_MAX)
    {
        return bLocal ? m_Cluster[uRank] : m_Master[uRank];
    }
    return m_Cluster[m_SrvData.uRank];
}

INLINE SERVER_CLUSTER& CSlaveServer::SyncCluster(UInt uRank)
{
    assert(uRank < COMMONR_MAX);
    if ((m_SrvData.uSync & (1 << uRank)) != 0)
    {
        return m_Master[uRank];
    }
    return m_Cluster[uRank];
}

INLINE void CSlaveServer::CleanCluster(void)
{
    if (m_SrvData.uSync != 0)
    {
        for (UInt i = COMMONR_MIN; i < m_SrvData.uRank; ++i)
        {
            UInt uSync = (1 << i);
            if ((m_SrvData.uSync & uSync) == 0)
            {
                continue;
            }

            SERVER_CLUSTER& Cluster = m_Cluster[i];
            {
                CSyncLockWaitScope scope(Cluster.Lock);
                Cluster.Info.RemoveAll();
                Cluster.Reset();
            }
        }
    }
}

#endif // __SLAVE_SERVER_H__
